package cn.iocoder.yudao.module.bpm.api.util;

import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

/**
 * 流程表单工具类   用于在提交审批的时候获取字段名和属性值   只能循环两层 业务暂时如此  以后再改成递归遍历
 * 1.如果属性为枚举  那么枚举必须实现baseEnum
 * 2.如果属性为对象  那么对象必须集成baseEntity
 *
 * @auther: chehao030
 * @date: 2020/03/19
 * @time: 11:03
 */
public class FormFlowFieldUtils {

    private static final String GETTER_NAME_PREFIX = "get";

    /**
     * 如果对象是自定义对象 那么必须集成baseEntity 递归版本  按照流程表单配置 list不用递归
     * TODO: 需要优化，若t对象是基础类型，例如String，则会生成大量无用的信息
     *
     * @param keyName key
     * @param t       对象
     * @return 表单要求list对象
     */
    public static <T> Map<String, Object> getFormFieldList(T t, String keyName) {
        if (t == null) {
            return null;
        }
        Class clazz = t.getClass();
        Field[] fields = clazz.getDeclaredFields();
        Method[] methods = clazz.getMethods();
        final Map<String, Object>[] result = new Map[]{new HashMap<String, Object>()};
        Arrays.asList(fields).forEach(k -> {
            k.setAccessible(true);
            String key = getKey(k, keyName);
            try {
                Object object = k.get(t);
                result[0] = getFormFieldKeyValueDto(result[0],object, key, keyName);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        Arrays.asList(methods).forEach(method -> {
            String key = getNameFromGetter(method.getName());
            if (StringUtils.isEmpty(key) || Objects.equals(key, "class")) {
                return;
            }
            final String methodName = key;
            //如果存在对应的字段，因为上面已经处理了，所以忽略
            boolean existsFields = Arrays.stream(fields).anyMatch(f -> Objects.equals(f.getName(), methodName));
            if (existsFields) {
                return;
            }
            if (!StringUtils.isEmpty(keyName)) {
                key = keyName + "_" + key;
            }
            if (method.getParameterCount() > 0) {
                return;
            }
            try {
                Object object = method.invoke(t);
                result[0] = getFormFieldKeyValueDto(result[0],object, key, keyName);
                //result.add(formFieldKeyValueDto);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        return result[0];
    }

    private static String getKey(Field k, String keyPrefix) {
        String key = k.getName();
        if (!StringUtils.isEmpty(keyPrefix)) {
            // 如果使用公共前缀，公共前缀存在
            if (!StringUtils.isEmpty(keyPrefix)) {
                return keyPrefix + "_" + key;
            }
        }
        // 不加前缀
        return key;
    }

    /**
     * 根据对象，key 构造FormFieldKeyValueDto对象
     *
     * @param object
     * @param key
     * @param keyName
     * @return
     */
    private static Map<String, Object> getFormFieldKeyValueDto(Map<String, Object> result, Object object, String key, String keyName) {
        if (object instanceof Date) {
            object = ((Date) object).getTime();

        }
        result.put(key,object);
        return result;
    }

    /**
     * 获取getter 的名称
     *
     * @param methodName
     * @return
     */
    public static String getNameFromGetter(String methodName) {
        if (StringUtils.isEmpty(methodName) || !methodName.startsWith(GETTER_NAME_PREFIX) || methodName.length() < 4) {
            return "";
        }
        return methodName.substring(3, 4).toLowerCase() + methodName.substring(4);
    }
}
